package com.example.servicedemo;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.BatteryManager;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //常见binder跨进程通信方式：
        //1.利用Service组件binderService方式获取IBinder通信
        bindServiceMeath();
        //2.通过ServiceManager.getService方式获取相关Manager其实就是IBinder
        getServiceMeath();
        //in 表示数据只能由客户端流向服务端。（表现为服务端修改此参数，不会影响客户端的对象）
        //out 表示数据只能由服务端流向客户端。（表现为服务端收到的参数是空对象，并且服务端修改对象后客户端会同步变动）
        //inout 则表示数据可在服务端与客户端之间双向流通。（表现为服务端能接收到客户端传来的完整对象，并且服务端修改对象后客户端会同步变动）
        //aidl关键字+双向通信+linkToDeath
        demoMeath();
        //Messenger基于AIDL实现的轻量级IPC方案
        messengerMeath();
 }

    private void bindServiceMeath() {
        Button aidl = findViewById(R.id.bn_aidl);
        aidl.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //1.binderService方式获取IBinder通信 基础简单示例：
                Intent intent = new Intent(MainActivity.this,MySampleService.class);
                bindService(intent, new ServiceConnection() {
                    @Override
                    public void onServiceConnected(ComponentName name, IBinder service) {
                        SampleStudentInterface sampleStudentInterface = SampleStudentInterface.Stub.asInterface(service);
                        try {
                            int getId  = sampleStudentInterface.getStudentId("");
                            Log.i("test","getId=" +getId);
                        } catch (RemoteException e) {
                            Log.i("test","RemoteException=" +e.getMessage());
                            e.printStackTrace();
                        }
                    }
                    @Override
                    public void onServiceDisconnected(ComponentName name) {
                        Log.i("test","client onServiceDisconnected name = " +name);
                    }
                }, BIND_AUTO_CREATE);
            }
        });
    }

    private void getServiceMeath() {
        BatteryManager manager = (BatteryManager) getSystemService(BATTERY_SERVICE);
        Log.i("test"," BATTERY_PROPERTY_CAPACITY "+manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)+" BATTERY_PROPERTY_CHARGE_COUNTER "+manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER)
                + " BATTERY_PROPERTY_CURRENT_AVERAGE "+manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE)
                + " BATTERY_PROPERTY_CURRENT_NOW "+manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_NOW));
    }

    private void demoMeath() {
        Button bn_aidl2 = findViewById(R.id.bn_aidl2);
        bn_aidl2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this,MyService.class);
                bindService(intent,serviceConnection , BIND_AUTO_CREATE);
            }
        });
    }

  private ServiceConnection serviceConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            IStudentInterface remoteInterface = IStudentInterface.Stub.asInterface(service);
            try {
                //in 表示数据只能由客户端流向服务端。（表现为服务端修改此参数，不会影响客户端的对象）
                StudentInfo studentInfoIn = new StudentInfo();
                studentInfoIn.setName("client");
                Log.i("test", "name=" + remoteInterface.getConvertName(studentInfoIn));
                Log.i("test", "-----------------------------------------------");
                //out 表示数据只能由服务端流向客户端。（表现为服务端收到的参数是空对象，并且服务端修改对象后客户端会同步变动）
                StudentInfo studentInfoOut = new StudentInfo();
                studentInfoOut.setId("200+");
                studentInfoOut.setName("clientOut");
                remoteInterface.getServiceStudentInfo(studentInfoOut);
                Log.i("test", "getServiceStudentInfo = " + studentInfoOut);
                Log.i("test", "-----------------------------------------------");
                //inout 则表示数据可在服务端与客户端之间双向流通。（表现为服务端能接收到客户端传来的完整对象，并且服务端修改对象后客户端会同步变动）
                StudentInfo studentInfoInOut = new StudentInfo();
                studentInfoInOut.setId("2001");
                studentInfoInOut.setName("clientInOut");
                remoteInterface.getServiceStudentInfoInOut(studentInfoInOut);
                Log.i("test", "getServiceStudentInfoInOut = " + studentInfoInOut);
                Log.i("test", "-----------------------------------------------");
                //双向通信
                remoteInterface.setCallback(new CallbackeService());
                int studentId = remoteInterface.changeStudentId("helloworld");
                Log.i("test", "getStudentId =" + studentId);
                int studentId1 = remoteInterface.changeStudentId("55");
                Log.i("test", "getStudentId1 =" + studentId1);
                Log.i("test", "-----------------------------------------------");
                //linkToDeath
                remoteInterface.testLinkToDeath(new CallbackeService());
                //主动延迟抛出一个异常来实现销毁服务端的目的
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        int i = 1 / 0;
                    }
                },5000);

            } catch (RemoteException e) {
                Log.i("test", "RemoteException =" + e.getMessage());
                e.printStackTrace();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("test", "onServiceDisconnected="+ name);
        }
    };

    class CallbackeService extends IChangeCallback.Stub {
        @Override
        public int changeData(int changeIndex) throws RemoteException {
            Log.i("test","changeIndex = " + changeIndex);
            return  changeIndex + 1;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (serviceConnection!=null){
            unbindService(serviceConnection);
        }
    }

    //----------------------------------------------------------
    private void messengerMeath() {
        //注册绑定
       registerLink();
       //发送消息到服务端
       findViewById(R.id.bn_messenger).setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               try {
                   sendMessageToServer();
               } catch (RemoteException e) {
                   Log.i("test","sendMessageToServer-RemoteException="+e.getMessage());
                   e.printStackTrace();
               }
           }
       });
    }
    Handler messengerHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            if (msg.what == 2) {
                Log.i("test","msg1 =" + msg.getData().getString("bundleKey"));
            }
            super.handleMessage(msg);
        }
    };

    Messenger messengerClientSend = new Messenger(messengerHandler);
    Messenger messengerServer = null;
    private void registerLink() {
        Intent intent = new Intent(MainActivity.this,MessengerService.class);
        bindService(intent, new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                try {
                    messengerServer = new Messenger(service);
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.i("test","error ",e);
                }
            }
            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.i("test","client onServiceDisconnected name = " +name);
            }
        }, BIND_AUTO_CREATE);
    }

    void sendMessageToServer() throws RemoteException {
        Message toServer = Message.obtain();
        toServer.replyTo = messengerClientSend;//用于在消息传递过程中建立双向通信的机制
        toServer.what = 1;
//        toServer.obj = "hello I send from client"; //注意不可以 传递非parcel的对象，这个只能给obj赋值为parcel类型对象否则报错
        Bundle bundle = new Bundle();
        bundle.putString("bundleKey","ClientMsg");
        toServer.setData(bundle);
        messengerServer.send(toServer);
    }
}